﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace FlowGauge
{
    public partial class MyFlowGauge : UserControl
    {
        private double _minValue = 0;
        private double _maxValue = 100;
        private double _currentValue = 50;
        private double _targetValue = 50;
        private bool _isAnimating = false;
        private Color _gaugeColor = Color.FromArgb(52, 152, 219);
        private Color _pointerColor = Color.FromArgb(231, 76, 60);
        private Color _scaleColor = Color.FromArgb(80, 80, 80);
        private Color _textColor = Color.FromArgb(52, 73, 94);
        private Color _titleColor = Color.FromArgb(120, 144, 156);
        private float _animationSpeed = 5f;
        private int _bevelSize = 8;
        private float _borderThickness = 1.5f;
        private string _title = "流量计";
        private string _unit = "t/h";
        private int _scaleCount = 10;
        private bool _showValue = true;
        private bool _showMinMax = true;
        private double _minWarning = 20;
        private double _maxWarning = 80;
        private Color _warningColor = Color.FromArgb(231, 76, 60);

        // 公共属性
        [Category("数据"), Description("仪表最小值")]
        public double MinValue
        {
            get => _minValue;
            set { _minValue = value; Invalidate(); }
        }

        [Category("数据"), Description("仪表最大值")]
        public double MaxValue
        {
            get => _maxValue;
            set { _maxValue = value; Invalidate(); }
        }

        [Category("数据"), Description("当前值")]
        public double CurrentValue
        {
            get => _currentValue;
            set
            {
                value = Math.Max(_minValue, Math.Min(_maxValue, value));
                if (Math.Abs(_currentValue - value) > 0.1)
                {
                    _targetValue = value;
                    if (!_isAnimating)
                    {
                        _isAnimating = true;
                        animationTimer.Start();
                    }
                }
                else
                {
                    _currentValue = value;
                    Invalidate();
                }
            }
        }

        [Category("外观"), Description("仪表颜色")]
        public Color GaugeColor
        {
            get => _gaugeColor;
            set { _gaugeColor = value; Invalidate(); }
        }

        [Category("外观"), Description("指针颜色")]
        public Color PointerColor
        {
            get => _pointerColor;
            set { _pointerColor = value; Invalidate(); }
        }

        [Category("外观"), Description("刻度颜色")]
        public Color ScaleColor
        {
            get => _scaleColor;
            set { _scaleColor = value; Invalidate(); }
        }

        [Category("外观"), Description("文本颜色")]
        public Color TextColor
        {
            get => _textColor;
            set { _textColor = value; Invalidate(); }
        }

        [Category("外观"), Description("标题颜色")]
        public Color TitleColor
        {
            get => _titleColor;
            set { _titleColor = value; Invalidate(); }
        }

        [Category("外观"), Description("动画速度")]
        public float AnimationSpeed
        {
            get => _animationSpeed;
            set { _animationSpeed = Math.Max(1f, value); }
        }

        [Category("外观"), Description("斜面尺寸")]
        public int BevelSize
        {
            get => _bevelSize;
            set { _bevelSize = Math.Max(0, value); Invalidate(); }
        }

        [Category("外观"), Description("边框厚度")]
        public float BorderThickness
        {
            get => _borderThickness;
            set { _borderThickness = Math.Max(0.5f, value); Invalidate(); }
        }

        [Category("文本"), Description("仪表标题")]
        public string Title
        {
            get => _title;
            set { _title = value; Invalidate(); }
        }

        [Category("文本"), Description("单位")]
        public string Unit
        {
            get => _unit;
            set { _unit = value; Invalidate(); }
        }

        [Category("刻度"), Description("主刻度数量")]
        public int ScaleCount
        {
            get => _scaleCount;
            set { _scaleCount = Math.Max(2, value); Invalidate(); }
        }

        [Category("显示"), Description("显示当前值")]
        public bool ShowValue
        {
            get => _showValue;
            set { _showValue = value; Invalidate(); }
        }

        [Category("显示"), Description("显示最小/最大值")]
        public bool ShowMinMax
        {
            get => _showMinMax;
            set { _showMinMax = value; Invalidate(); }
        }

        [Category("报警"), Description("最小警告值")]
        public double MinWarning
        {
            get => _minWarning;
            set { _minWarning = value; Invalidate(); }
        }

        [Category("报警"), Description("最大警告值")]
        public double MaxWarning
        {
            get => _maxWarning;
            set { _maxWarning = value; Invalidate(); }
        }

        [Category("报警"), Description("警告颜色")]
        public Color WarningColor
        {
            get => _warningColor;
            set { _warningColor = value; Invalidate(); }
        }

        // 动画计时器
        private readonly Timer animationTimer;

        public MyFlowGauge()
        {
            SetStyle(ControlStyles.OptimizedDoubleBuffer |
                     ControlStyles.ResizeRedraw |
                     ControlStyles.UserPaint |
                     ControlStyles.AllPaintingInWmPaint, true);

            Size = new Size(250, 250);
            DoubleBuffered = true;
            Font = new Font("Microsoft YaHei UI", 9f);

            // 初始化动画计时器
            animationTimer = new Timer { Interval = 20 }; // 50fps
            animationTimer.Tick += AnimationTimer_Tick;
        }

        private void AnimationTimer_Tick(object sender, EventArgs e)
        {
            // 平滑过渡到目标值
            if (Math.Abs(_currentValue - _targetValue) < 0.1)
            {
                _currentValue = _targetValue;
                animationTimer.Stop();
                _isAnimating = false;
            }
            else
            {
                _currentValue += (_targetValue - _currentValue) / _animationSpeed;
            }

            Invalidate();
        }

        protected override void OnPaint(PaintEventArgs e)
        {
            base.OnPaint(e);

            var g = e.Graphics;
            g.SmoothingMode = SmoothingMode.AntiAlias;
            g.TextRenderingHint = System.Drawing.Text.TextRenderingHint.ClearTypeGridFit;

            // 绘制背景
            DrawBackground(g);

            // 绘制仪表盘
            DrawGauge(g);
        }

        private void DrawBackground(Graphics g)
        {
            // 绘制背景渐变
            using (var bgBrush = new LinearGradientBrush(
                ClientRectangle,
                Color.FromArgb(250, 250, 252),
                Color.FromArgb(240, 242, 245),
                90f))
            {
                //g.FillRectangle(bgBrush, ClientRectangle);
                g.FillEllipse(bgBrush, ClientRectangle);
            }

            // 绘制边框
            using (var borderPen = new Pen(_titleColor, _borderThickness))
            {
                g.DrawEllipse(borderPen,
                    _borderThickness / 2,
                    _borderThickness / 2,
                    Width - _borderThickness,
                    Height - _borderThickness);
            }

            // 绘制内部阴影
            if (_bevelSize > 0)
            {
                using (var highlightPen = new Pen(Color.FromArgb(200, 255, 255, 255), 1))
                {
                    // 左上高光
                    g.DrawArc(highlightPen, _bevelSize, _bevelSize,
                              Width - 2 * _bevelSize, Height - 2 * _bevelSize,
                              135, 180);
                }

                using (var shadowPen = new Pen(Color.FromArgb(60, 0, 0, 0), 1))
                {
                    // 右下阴影
                    g.DrawArc(shadowPen, _bevelSize, _bevelSize,
                              Width - 2 * _bevelSize, Height - 2 * _bevelSize,
                              315, 180);
                }
            }
        }

        private void DrawGauge(Graphics g)
        {
            // 计算中心点和半径
            int centerX = Width / 2;
            int centerY = Height / 2;
            int radius = Math.Min(centerX, centerY) - 20;

            // 绘制警告区域
            DrawWarningZone(g, centerX, centerY, radius);

            // 绘制刻度环
            DrawScaleRing(g, centerX, centerY, radius);

            // 绘制刻度
            DrawScales(g, centerX, centerY, radius);

            // 绘制指针
            DrawPointer(g, centerX, centerY, radius);

            // 绘制中心点
            DrawCenterPoint(g, centerX, centerY);

            // 绘制文本
            DrawText(g, centerX, centerY);
        }

        private void DrawWarningZone(Graphics g, int centerX, int centerY, int radius)
        {
            // 计算警告区域的角度
            float minAngle = ValueToAngle(_minWarning);
            float maxAngle = ValueToAngle(_maxWarning);

            // 绘制警告区域
            using (var warningBrush = new SolidBrush(Color.FromArgb(40, _warningColor)))
            {
                // 警告区域在刻度环外
                int warningRadius = radius + 5;
                Rectangle rect = new Rectangle(centerX - warningRadius, centerY - warningRadius,
                                              warningRadius * 2, warningRadius * 2);

                // 绘制警告弧段
                g.FillPie(warningBrush, rect, minAngle, maxAngle - minAngle);
            }
        }

        private void DrawScaleRing(Graphics g, int centerX, int centerY, int radius)
        {
            // 绘制外环
            using (var outerPen = new Pen(_titleColor, 2f))
            {
                g.DrawEllipse(outerPen, centerX - radius, centerY - radius,
                              radius * 2, radius * 2);
            }

            // 绘制内环
            using (var innerPen = new Pen(Color.FromArgb(200, 200, 210), 1f))
            {
                g.DrawEllipse(innerPen, centerX - radius + 5, centerY - radius + 5,
                              (radius - 5) * 2, (radius - 5) * 2);
            }

            // 绘制渐变环
            using (var gradientPen = new Pen(new LinearGradientBrush(
                new Point(centerX - radius, centerY),
                new Point(centerX + radius, centerY),
                Color.Transparent, _gaugeColor)))
            {
                gradientPen.Width = 8;
                g.DrawArc(gradientPen, centerX - radius + 10, centerY - radius + 10,
                          (radius - 10) * 2, (radius - 10) * 2,
                          135, 270);
            }
        }

        private void DrawScales(Graphics g, int centerX, int centerY, int radius)
        {
            // 刻度长度
            int mainScaleLength = 15;
            int subScaleLength = 8;

            // 角度范围 (225度)
            float startAngle = 135; // 从左上开始
            float sweepAngle = 270; // 顺时针270度

            // 绘制主刻度和子刻度
            int totalScales = _scaleCount * 5; // 每个主刻度5个子刻度
            float anglePerScale = sweepAngle / totalScales;

            using (var scalePen = new Pen(_scaleColor, 1.5f))
            using (var font = new Font(Font.FontFamily, 8, FontStyle.Bold))
            using (var brush = new SolidBrush(_textColor))
            {
                for (int i = 0; i <= totalScales; i++)
                {
                    float angle = startAngle + i * anglePerScale;
                    float radian = angle * (float)Math.PI / 180f;

                    // 计算刻度起点和终点
                    int startX = centerX + (int)((radius - 5) * Math.Cos(radian));
                    int startY = centerY + (int)((radius - 5) * Math.Sin(radian));

                    int endX, endY;

                    // 主刻度
                    if (i % 5 == 0)
                    {
                        endX = centerX + (int)((radius - 5 - mainScaleLength) * Math.Cos(radian));
                        endY = centerY + (int)((radius - 5 - mainScaleLength) * Math.Sin(radian));

                        // 绘制主刻度
                        g.DrawLine(scalePen, startX, startY, endX, endY);

                        // 绘制刻度值
                        double value = _minValue + (i * (_maxValue - _minValue) / totalScales);
                        string label = value.ToString("0");

                        // 计算文本位置
                        int textRadius = radius - 25;
                        int textX = centerX + (int)(textRadius * Math.Cos(radian));
                        int textY = centerY + (int)(textRadius * Math.Sin(radian));

                        var size = g.MeasureString(label, font);
                        g.DrawString(label, font, brush,
                                    textX - size.Width / 2,
                                    textY - size.Height / 2);
                    }
                    // 子刻度
                    else
                    {
                        endX = centerX + (int)((radius - 5 - subScaleLength) * Math.Cos(radian));
                        endY = centerY + (int)((radius - 5 - subScaleLength) * Math.Sin(radian));

                        // 绘制子刻度
                        g.DrawLine(scalePen, startX, startY, endX, endY);
                    }
                }
            }
        }

        private void DrawPointer(Graphics g, int centerX, int centerY, int radius)
        {
            // 计算指针角度
            float angle = ValueToAngle(_currentValue);
            float radian = angle * (float)Math.PI / 180f;

            // 计算指针终点
            int pointerLength = radius - 30;
            int endX = centerX + (int)(pointerLength * Math.Cos(radian));
            int endY = centerY + (int)(pointerLength * Math.Sin(radian));

            // 绘制指针
            using (var pointerPen = new Pen(_pointerColor, 3f))
            {
                g.DrawLine(pointerPen, centerX, centerY, endX, endY);
            }

            // 绘制指针头
            using (var pointerBrush = new SolidBrush(_pointerColor))
            {
                g.FillEllipse(pointerBrush, endX - 5, endY - 5, 10, 10);

                // 指针头高光
                using (var highlightBrush = new SolidBrush(Color.White))
                {
                    g.FillEllipse(highlightBrush, endX - 2, endY - 2, 4, 4);
                }
            }
        }

        private void DrawCenterPoint(Graphics g, int centerX, int centerY)
        {
            // 绘制中心圆
            using (var centerBrush = new SolidBrush(Color.White))
            {
                g.FillEllipse(centerBrush, centerX - 10, centerY - 10, 20, 20);
            }

            // 绘制中心点
            using (var centerBrush = new SolidBrush(_pointerColor))
            {
                g.FillEllipse(centerBrush, centerX - 5, centerY - 5, 10, 10);
            }

            // 中心点高光
            using (var highlightBrush = new SolidBrush(Color.White))
            {
                g.FillEllipse(highlightBrush, centerX - 2, centerY - 2, 4, 4);
            }
        }

        private void DrawText(Graphics g, int centerX, int centerY)
        {
            // 绘制标题
            using (var titleFont = new Font("Microsoft YaHei UI", 12, FontStyle.Bold))
            using (var brush = new SolidBrush(_titleColor))
            {
                var size = g.MeasureString(_title, titleFont);
                g.DrawString(_title, titleFont, brush,
                            centerX - size.Width / 2,
                            centerY + 45);
            }

            // 绘制当前值
            if (_showValue)
            {
                using (var valueFont = new Font("Microsoft YaHei UI", 16, FontStyle.Bold))
                using (var brush = new SolidBrush(_textColor))
                {
                    string valueText = $"{_currentValue:0.0} {_unit}";
                    var size = g.MeasureString(valueText, valueFont);
                    g.DrawString(valueText, valueFont, brush,
                                centerX - size.Width / 2,
                                centerY + 15);
                }
            }

            // 绘制最小/最大值
            if (_showMinMax)
            {
                using (var minMaxFont = new Font("Microsoft YaHei UI", 8, FontStyle.Regular))
                using (var brush = new SolidBrush(_titleColor))
                {
                    string minText = $"{_minValue:0}";
                    string maxText = $"{_maxValue:0}";

                    var minSize = g.MeasureString(minText, minMaxFont);
                    var maxSize = g.MeasureString(maxText, minMaxFont);

                    // 左下角
                    g.DrawString(minText, minMaxFont, brush,
                                centerX - 50,
                                centerY + 50);

                    // 右下角
                    g.DrawString(maxText, minMaxFont, brush,
                                centerX + 50 - maxSize.Width,
                                centerY + 50);
                }
            }
        }

        private float ValueToAngle(double value)
        {
            // 角度范围 (225度)
            float startAngle = 135; // 从左上开始
            float sweepAngle = 270; // 顺时针270度

            // 计算值在范围内的比例
            double ratio = (value - _minValue) / (_maxValue - _minValue);

            // 返回对应角度
            return startAngle + (float)(sweepAngle * ratio);
        }

        protected override void OnResize(EventArgs e)
        {
            base.OnResize(e);
            // 保持控件为正方形
            if (Width != Height)
            {
                Size = new Size(Math.Min(Width, Height), Math.Min(Width, Height));
            }
            Invalidate();
        }

        protected override void Dispose(bool disposing)
        {
            if (disposing)
            {
                animationTimer?.Stop();
                animationTimer?.Dispose();
            }
            base.Dispose(disposing);
        }
    }
}
